package com.cskaoyan._11polymorphic._03advantages;

/**
 * @description:
 * @author: 景天
 * @date: 2023/2/10 15:12
 **/
/*
> 科学家要收集动物的叫声去研究，先要收集猫，狗两种动物的叫声研究。
随后又扩展到其它动物，最后又需要研究人类。
我们可以先定义一个顶层父类Animal作为父类，然后定义具体动物类：猫和狗。
假如收集每种动物的叫声研究，都需要写一个方法，显然过于麻烦，程序扩展性也太差了。所以我们可以这么做：
1. 写一个方法来收集研究动物的叫声，方法的形参不写具体动物类，而写顶层祖先类：Animal。然后在方法体中，调用叫的方法即可。
2. 这样该方法在调用传参时，就可以Animal不同的子类对象了。这仍然是一个父类引用指向子类对象

这就是多态一个基本的使用案例，当传入方法不同的子类对象时，方法执行时就会根据不同的具体对象类型，来决定行为。

优点:
    代码复用
    进行扩展
缺点:
    在多态中,父类引用指向了子类对象,因为父类引用的限制,无法访问子类独有的方法

 */
public class Demo2 {
    public static void main(String[] args) {
        // 测试
        //collectCatVoice(new Cat());
        //
        //collectDogVoice(new Dog());
        //
        //collectHumanVoice(new Human());

        collectAnimalVoice(new Cat());
        collectAnimalVoice(new Dog());
        collectAnimalVoice(new Human());
    }

    // 专门接收猫叫的方法
    // 参数需要一个Cat类型
    public static void collectCatVoice(Cat cat) {
        cat.shout();
    }

    // 专门用来收集狗叫的方法
    // 参数需要Dog类型
    public static void collectDogVoice(Dog dog) {
        dog.shout();
    }

    // 专门用来收集人类的叫声的方法
    // 参数需要Human类型
    public static void collectHumanVoice(Human human) {

        human.shout();
    }

    // 如果说要研究更多的动物,要写很多收集声音的方法
    // 考虑能不能进行代码复用,写一个一劳永逸的方法,只要研究的是动物,写一个收集动物声音的方法
    public static void collectAnimalVoice(Animal animal) {
        // 能否调用子类独有的方法
        // 不能调用自乐独有的方法,多态中,访问范围取决于引用的类型
        // 如果非要访问子类独有的方法怎么办??
        // 强制类型转换,可能会出现问题, 传的参数是Cat,无法把Cat转成Human
        // 再进行强制类型转换之前,做判读
        if (animal instanceof Human) {
            ((Human) animal).work();
        }
        animal.shout();
    }
}

class Animal{
    public void shout() {
        System.out.println("动物叫");
    }
}

class Cat extends Animal{

    @Override
    public void shout() {
        System.out.println("喵喵喵");
    }
}

class Dog extends Animal{

    @Override
    public void shout() {
        System.out.println("汪汪汪");
    }
}

class Human extends Animal{

    @Override
    public void shout() {
        System.out.println("哈哈哈哈哈");
    }

    // 人类自己独有的方法
    public void work() {
        System.out.println("996福报,大家都是兄弟,是兄弟都来砍我!! 我喜欢加班");
    }
}